#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "ohos_init.h"
#include "ohos_types.h"
#include "cmsis_os2.h"
#include "wifi_device.h"
#include "wifi_error_code.h"
#include "lwip/netifapi.h"
#include "lwip/api_shell.h"

#define DEF_TIMEOUT 30
#define WIFI_SSID "YOUR_WIFI_SSID" // 此处为要连接的热点的 SSID（不超过 32 个字符）
#define WIFI_PASSWORD "1234567890" // 此处为热点的密码（需大于等于 8 个字符）
#define WIFI_SECURITYTYPE WIFI_SEC_TYPE_PSK // 此处为热点的加密方式

static struct netif *g_lwip_netif = NULL;
static int g_staScanSuccess = 0;
static int g_connectSuccess = 0;
static int ssid_count = 0;

static void OnWifiScanStateChangedHandler(int state, int size)
{
    if (size > 0)
    {
        ssid_count = size;
        g_staScanSuccess = 1;
    }
}

static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info)
{
    if (state > 0)
    {
        g_connectSuccess = 1;
        printf("Wifi connect successfully\n");
    }
    else
    {
        printf("Connect error, please check password!\n");
    }
}

static WifiEvent g_eventListener =
{
    .OnWifiScanStateChanged = OnWifiScanStateChangedHandler,
    .OnWifiConnectionChanged = OnWifiConnectionChangedHandler
};

static void WifiSTATask(void)
{
    WifiErrorCode error;
    unsigned int size = WIFI_SCAN_HOTSPOT_LIMIT;
    WifiScanInfo *info = malloc(sizeof(WifiScanInfo) * size);
    WifiDeviceConfig config = {0};
    // 注册 Wi-Fi 回调
    if (RegisterWifiEvent(&g_eventListener) != WIFI_SUCCESS)
    {
        printf("Register wifi event failed!\n");
        return;
    }
    // 使能 Wi-Fi
    if (EnableWifi() != WIFI_SUCCESS)
    {
        printf("EnableWifi failed\n");
        return;
    }
    // 判断 Wi-Fi 是否激活
    if (IsWifiActive() == 0)
    {
        printf("Wifi station is not actived\n");
        return;
    }
    // 轮询查找 Wi-Fi 列表
    while (g_staScanSuccess != 1)
    {
        // 重置标志位
        ssid_count = 0;
        g_staScanSuccess = 0;
        // 开始扫描
        Scan();
        // 等待扫描结果
        int scanTimeout = DEF_TIMEOUT;
        while (scanTimeout > 0)
        {
            sleep(1);
            scanTimeout--;
            if (g_staScanSuccess == 1)
            {
                printf("WaitScanResult success %ds\n", (DEF_TIMEOUT - scanTimeout));
                break;
            }
        }
        if (scanTimeout <= 0)
        {
            printf("WaitScanResult timeout!\n");
            continue;
        }
        // 获取扫描列表
        GetScanInfoList(info, &size);
    }
    // 连接指定的 Wi-Fi 热点
    uint8_t i = 0;
    for (; i < ssid_count; i++)
    {
        if (strcmp(WIFI_SSID, info[i].ssid) == 0)
        {
            int result;
            printf("Select: %3d, Waiting...\n", i + 1);
            // 配置热点信息
            strcpy_s(config.ssid, sizeof(config.ssid), info[i].ssid);
            strcpy_s(config.preSharedKey, sizeof(config.preSharedKey), WIFI_PASSWORD);
            config.securityType = WIFI_SECURITYTYPE;
            if (AddDeviceConfig(&config, &result) != WIFI_SUCCESS)
            {
                printf("AddDeviceConfig failed\n");
                return;
            }
            // 连接至热点
            if (ConnectTo(result) != WIFI_SUCCESS)
            {
                printf("Connect to wifi failed\n");
                return;
            }
            // 等待连接结果
            int connectTimeout = DEF_TIMEOUT;
            while (connectTimeout > 0)
            {
                sleep(1);
                connectTimeout--;
                if (g_connectSuccess == 1)
                {
                    printf("WaitConnectResult success %ds\n", (DEF_TIMEOUT - connectTimeout));
                    g_lwip_netif = netifapi_netif_find("wlan0");
                    break;
                }
            }
            if (connectTimeout <= 0)
            {
                printf("WaitConnectResult timeout!\n");
                return;
            }
            break;
        }
    }
    if (i == ssid_count)
    {
        printf("Can not find expected wifi\n");
        return;
    }
    // 启动 DHCP
    if (g_lwip_netif)
    {
        printf("Start DHCP\n");
        netifapi_dhcp_start(g_lwip_netif);
    }
    // 等待 DHCP
    while (1)
    {
        osDelay(100);
        if (netifapi_dhcp_is_bound(g_lwip_netif) == ERR_OK)
        {
            printf("DHCP OK\n");
            ip4_addr_t ip_addr = {0};
            ip4_addr_t netmask = {0};
            ip4_addr_t gateway = {0};
            err_t ret = netifapi_netif_get_addr(g_lwip_netif, &ip_addr, &netmask, &gateway);
            if (ret == ERR_OK)
            {
                printf("ip: %s, ", ip4addr_ntoa(&ip_addr));
                printf("netmask: %s, ", ip4addr_ntoa(&netmask));
                printf("gateway: %s\n", ip4addr_ntoa(&gateway));
            }
            break;
        }
    }
}

void WIFISTADemo(void)
{
    osThreadAttr_t attr;
    attr.name = "WIFISTADemo";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 8192; // 注意此处需要为任务分配更大的栈空间，否则会溢出
    attr.priority = osPriorityNormal;
    if (osThreadNew((osThreadFunc_t) WifiSTATask, NULL, &attr) == NULL)
    {
        printf("Failed to create WifiSTATask!\n");
    }
}

SYS_RUN(WIFISTADemo);
